package com.park.platform.service.impl;

import com.park.common.bean.OrderInputView;
import com.park.common.bean.PageBean;
import com.park.common.constant.IDBConstant;
import com.park.common.constant.IPlatformConstant;
import com.park.common.exception.MessageException;
import com.park.common.poo.*;
import com.park.common.util.*;
import com.park.platform.dao.IBaseDao;
import com.park.platform.service.*;
import com.park.wx.WeiXinConnector;
import com.park.wx.http.HttpConnect;
import com.park.wx.util.ConfigUtil;
import com.park.wx.util.PayCommonUtil;
import com.park.wx.util.SignUtil;
import com.park.wx.util.XMLUtil;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.*;

/**
 * Created by Administrator on 2017-05-01.
 */
@Service
public class TmOrderServiceImpl extends BaseService implements ITmOrderService {

    private static Logger logger = Logger.getLogger(TmOrderServiceImpl.class);

    @Autowired
    private IBaseDao baseDao;

    @Autowired
    private IActivityService activityService;

    @Autowired
    private IOperatorService operatorService;

    @Autowired
    private IExpressService expressService;

    @Autowired
    private IAreaService areaService;

    @Autowired
    private IConfigService configService;


    @Override
    public Map<String, Object> toOrder(int activityId, Integer uid){
        ActivityInfo activityInfo = activityService.getActivityInfo(activityId);
        if(activityInfo == null) throw new MessageException("活动不存在");
        activityInfo.setActivityPic(FileUtil.getImgHttp(activityInfo.getActivityPic()));
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("activityInfo", activityInfo);
        if(uid != null) {
            List<Map<String, Object>> expressList = expressService.getExpressList(uid);
            resultMap.put("expressList", expressList);
        }
        return resultMap;
    }

    @Override
    public void saveOrderInfo(OrderInfo orderInfo, OrderDetail orderDetail){
        Integer activityId = orderDetail.getActivityId();
        ActivityInfo activityInfo = activityService.getActivityInfo(activityId);
        if(activityInfo == null) throw new MessageException("操作错误");
        if(orderDetail.getItemCount() > activityInfo.getActivityInventory()) throw new MessageException("图腾剩余数量不足，目前剩余：" + activityInfo.getActivityInventory());

        ExpressInfo expressInfo = expressService.getExpressInfo(orderInfo.getExpressId());
        if(expressInfo == null) throw new MessageException("请选择快递地址");

        if(orderDetail.getItemCount() == null || orderDetail.getItemCount() <= 0) throw new MessageException("请选择图腾数量");

        String nowDate = DateUtil.getNowDate();

        //activityInfo.setActivityInventory(activityInfo.getActivityInventory() - orderDetail.getItemCount()); //支付成功才减库存
        baseDao.save(activityInfo, activityInfo.getActivityId());

        //保存快递历史
        ExpressRealInfo expressRealInfo = JsonUtils.fromJson(JsonUtils.fromJsonDF(expressInfo), ExpressRealInfo.class);
        expressRealInfo.setExpressId(null);
        expressRealInfo.setCreateTime(nowDate);
        baseDao.save(expressRealInfo, null);

        orderDetail.setCreateTime(nowDate);
        orderDetail.setItemPrice(activityInfo.getActivityPrice());
        orderDetail.setItemName(activityInfo.getActivityName());
        orderDetail.setItemTitle(activityInfo.getActivityTitle());

        BigDecimal itemSumPrice = Arith.getBigDecimal(Arith.mul(activityInfo.getActivityPrice().doubleValue(), orderDetail.getItemCount()));
        orderDetail.setItemSumPrice(itemSumPrice);

        //订单快递id是历史表的快递id
        orderInfo.setExpressId(expressRealInfo.getExpressId());
        orderInfo.setCreateTime(nowDate);
        orderInfo.setOrderSumPrice(itemSumPrice);
        orderInfo.setPayStatus(itemSumPrice.doubleValue() > 0 ? IDBConstant.LOGIC_STATUS_NO : IDBConstant.LOGIC_STATUS_YES);
        orderInfo.setOrderStatus(IDBConstant.LOGIC_STATUS_NO);
        baseDao.save(orderInfo, null);

        //生成订单号
        OrderInfo orderInfoNo = getOrderInfo(orderInfo.getOrderId());
        orderInfoNo.setOrderNo(DateUtil.formatDate(new Date(), DateUtil.YYYYMMDD_S) + orderInfo.getOrderId());
        baseDao.save(orderInfo, orderInfo.getOrderId());

        orderDetail.setOrderId(orderInfo.getOrderId());
        baseDao.save(orderDetail, null);

        expressService.clearDefaultExpress(orderInfo.getId());

        expressInfo.setDefaultFlag(IDBConstant.LOGIC_STATUS_YES);
        baseDao.save(expressInfo, expressInfo.getExpressId());
    }

    @Override
    public String wxPayPackage(int oId, String openId) throws Exception {

        OrderInfo orderInfo = getOrderInfo(oId);

        //openId = "oTK5utzXi_A2q8aus80Y60__LzY0";
        // 1 参数
        // 订单号
        String orderId = orderInfo.getOrderId() + "_" + System.currentTimeMillis();
        // 附加数据 原样返回
        String attach = "cxs";
        // 总金额以分为单位，不带小数点
        String totalFee = StrUtil.getMoney(StrUtil.objToStr(orderInfo.getOrderSumPrice().doubleValue()));

        // 订单生成的机器 IP
        String spbill_create_ip = "127.0.0.1";
        // 这里notify_url是 支付完成后微信发给该链接信息，可以判断会员是否支付成功，改变订单状态等。
        String notify_url = WeiXinConnector.DOMIAN + "/order/asynNotify";
        String trade_type = "JSAPI";

        // ---必须参数
        // 商户号
        String mch_id = WeiXinConnector.MCH_ID;
        // 随机字符串
        String nonce_str = StrUtil.getNonceStr();

        // 商品描述根据情况修改
        String body = "图腾购买";

        // 商户订单号
        String out_trade_no = orderId;

        SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
        packageParams.put("appid", WeiXinConnector.APP_ID);
        packageParams.put("mch_id", mch_id);
        packageParams.put("nonce_str", nonce_str);
        packageParams.put("body", body);
        packageParams.put("attach", attach);
        packageParams.put("out_trade_no", out_trade_no);

        // 这里写的金额为1 分到时修改
        packageParams.put("total_fee", totalFee);
        packageParams.put("spbill_create_ip", spbill_create_ip);
        packageParams.put("notify_url", notify_url);

        packageParams.put("trade_type", trade_type);
        packageParams.put("openid", openId);
        String sign = PayCommonUtil.createSign("UTF-8", packageParams);
        packageParams.put("sign", sign);

        String requestXML = PayCommonUtil.getRequestXml(packageParams);
        logger.info("requestXML：" + requestXML);
        Map map = XMLUtil.doXMLParse(HttpConnect.httpsRequestStr(ConfigUtil.UNIFIED_ORDER_URL, "POST", requestXML));

        String prepay_id = map.get("prepay_id").toString();
        logger.info("获取到的预支付ID：" + prepay_id);

        //获取prepay_id后，拼接最后请求支付所需要的package

        SortedMap<Object, Object> finalpackage = new TreeMap<Object, Object>();
        String timestamp = SignUtil.getTimeStamp();
        String packages = "prepay_id="+prepay_id;
        finalpackage.put("appId", WeiXinConnector.APP_ID);
        finalpackage.put("timeStamp", timestamp);
        finalpackage.put("nonceStr", nonce_str);
        finalpackage.put("package", packages);
        finalpackage.put("signType", "MD5");
        //要签名
        String finalsign = PayCommonUtil.createSign("UTF-8", finalpackage);

        String finaPackage = "\"appId\":\"" + WeiXinConnector.APP_ID + "\",\"timeStamp\":\"" + timestamp
                + "\",\"nonceStr\":\"" + nonce_str + "\",\"package\":\""
                + packages + "\",\"signType\" : \"MD5" + "\",\"paySign\":\""
                + finalsign + "\"";

        logger.info("V3 jsApi package:"+finaPackage);
        return finaPackage;
    }

    @Override
    public String getCodeurl(int oId) throws Exception {

        OrderInfo orderInfo = getOrderInfo(oId);
        // 1 参数
        // 订单号
        String orderId = orderInfo.getOrderId() + "_" + System.currentTimeMillis();
        // 附加数据 原样返回
        String attach = "cxs";
        // 总金额以分为单位，不带小数点
        String totalFee = StrUtil.getMoney(StrUtil.objToStr(orderInfo.getOrderSumPrice().doubleValue()));

        // 订单生成的机器 IP
        String spbill_create_ip = "127.0.0.1";
        // 这里notify_url是 支付完成后微信发给该链接信息，可以判断会员是否支付成功，改变订单状态等。
        String notify_url = WeiXinConnector.DOMIAN + "/order/asynNotify";
        String trade_type = "NATIVE";

        // ---必须参数
        // 商户号
        String mch_id = WeiXinConnector.MCH_ID;
        // 随机字符串
        String nonce_str = StrUtil.getNonceStr();

        // 商品描述根据情况修改
        String body = "图腾购买";

        // 商户订单号
        String out_trade_no = orderId;

        SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
        packageParams.put("appid", WeiXinConnector.APP_ID);
        packageParams.put("mch_id", mch_id);
        packageParams.put("nonce_str", nonce_str);
        packageParams.put("body", body);
        packageParams.put("attach", attach);
        packageParams.put("out_trade_no", out_trade_no);

        // 这里写的金额为1 分到时修改
        packageParams.put("total_fee", totalFee);
        packageParams.put("spbill_create_ip", spbill_create_ip);
        packageParams.put("notify_url", notify_url);

        packageParams.put("trade_type", trade_type);


        String sign = PayCommonUtil.createSign("UTF-8", packageParams);
        packageParams.put("sign", sign);

        String requestXML = PayCommonUtil.getRequestXml(packageParams);
        logger.info("requestXML：" + requestXML);
        Map map = XMLUtil.doXMLParse(HttpConnect.httpsRequestStr(ConfigUtil.UNIFIED_ORDER_URL, "POST", requestXML));

        String xml = "<xml>" + "<appid>" + WeiXinConnector.APP_ID + "</appid>" + "<mch_id>"
                + mch_id + "</mch_id>" + "<nonce_str>" + nonce_str
                + "</nonce_str>" + "<sign>" + sign + "</sign>"
                + "<body><![CDATA[" + body + "]]></body>"
                + "<out_trade_no>" + out_trade_no
                + "</out_trade_no>" + "<attach>" + attach + "</attach>"
                + "<total_fee>" + totalFee + "</total_fee>"
                + "<spbill_create_ip>" + spbill_create_ip
                + "</spbill_create_ip>" + "<notify_url>" + notify_url
                + "</notify_url>" + "<trade_type>" + trade_type
                + "</trade_type>" + "</xml>";
        String code_url = "";
        String createOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";


        code_url = PayCommonUtil.getCodeUrl(createOrderURL, xml);
        System.out.println("code_url----------------"+code_url);

        return code_url;
    }

    @Override
    public void asynNotify(String msgxml, HttpServletResponse response) throws Exception{
        Map map = XMLUtil.doXMLParse(msgxml);

        String result_code=(String) map.get("result_code");
        String out_trade_no  = (String) map.get("out_trade_no");
        String total_fee  = (String) map.get("total_fee");
        String sign  = (String) map.get("sign");
        Double amount = new Double(total_fee) / 100;//获取订单金额
        System.out.println("qianming");
        if(result_code.equals("SUCCESS")){
            System.out.println("qianming_success");
            //验证签名
            String fee_type  = (String) map.get("fee_type");
            String bank_type  = (String) map.get("bank_type");
            String cash_fee  = (String) map.get("cash_fee");
            String is_subscribe  = (String) map.get("is_subscribe");
            String nonce_str  = (String) map.get("nonce_str");
            String openid  = (String) map.get("openid");
            String return_code  = (String) map.get("return_code");
            String sub_mch_id  = (String) map.get("sub_mch_id");
            String time_end  = (String) map.get("time_end");
            String trade_type  = (String) map.get("trade_type");
            String transaction_id  = (String) map.get("transaction_id");
            String attach  = (String) map.get("attach");

            //需要对以下字段进行签名
            SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
            packageParams.put("appid", WeiXinConnector.APP_ID);
            packageParams.put("bank_type", bank_type);
            packageParams.put("cash_fee", cash_fee);
            packageParams.put("fee_type", fee_type);
            packageParams.put("is_subscribe", is_subscribe);
            packageParams.put("mch_id", WeiXinConnector.MCH_ID);
            packageParams.put("nonce_str", nonce_str);
            packageParams.put("openid", openid);
            packageParams.put("out_trade_no", out_trade_no);
            packageParams.put("result_code", result_code);
            packageParams.put("return_code", return_code);
            packageParams.put("sub_mch_id", sub_mch_id);
            packageParams.put("time_end", time_end);
            packageParams.put("total_fee", total_fee); //用自己系统的数据：订单金额
            packageParams.put("trade_type", trade_type);
            packageParams.put("transaction_id", transaction_id);
            packageParams.put("attach", attach);

            String endsign = PayCommonUtil.createSign("UTF-8", packageParams);
            System.out.println("qianming_1");
            if(sign.equals(endsign)){//验证签名是否正确  官方签名工具地址：https://pay.weixin.qq.com/wiki/tools/signverify/
                System.out.println("qianming_1_success");
                //处理自己的业务逻辑
                logger.info("支付成功!");
                updateCommission(StrUtil.objToInt(out_trade_no.substring(0, out_trade_no.indexOf("_"))));
                response.getWriter().write(setXML("SUCCESS", "OK"));    //告诉微信已经收到通知了
                /*BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
                out.write(setXML("SUCCESS", "OK").getBytes());
                out.flush();
                out.close();*/
            }else{
                System.out.println("qianming_1_fail");
                logger.info("sign===>" + sign);
                logger.info("endsign===>" + endsign);
                logger.info("验证签名不正确");
            }
        }else{
            System.out.println("qianming_1_null");
            response.getWriter().write(setXML("FAIL", "报文为空"));
        }
    }

    private String setXML(String return_code, String return_msg) {
        return "<xml><return_code><![CDATA[" + return_code + "]]></return_code><return_msg><![CDATA[" + return_msg + "]]></return_msg></xml>";
    }

    private void updateCommission(int orderId){

        OrderInfo orderInfo = getOrderInfo(orderId);

        if(orderInfo == null || IDBConstant.LOGIC_STATUS_YES.equals(orderInfo.getPayStatus())) return;

        orderInfo.setPayStatus(IDBConstant.LOGIC_STATUS_YES);
        baseDao.save(orderInfo, orderId);

        String nowDateStr = DateUtil.dateToString(new Date(), DateUtil.YYYYMMDD);

        SystemMeritInfo systemMeritInfo = new SystemMeritInfo();
        systemMeritInfo.setId(orderInfo.getId());
        systemMeritInfo.setCreateTime(DateUtil.getNowDate());
        systemMeritInfo.setPoint(StrUtil.objToInt(orderInfo.getOrderSumPrice().doubleValue() * IPlatformConstant.MULTIPLE)); //功德值*10倍活动价格
        systemMeritInfo.setCreateDate(nowDateStr);
        systemMeritInfo.setServiceType(IDBConstant.LOGIC_STATUS_YES);
        baseDao.save(systemMeritInfo, null);

        UserOperator findUser = operatorService.getUserOperator(orderInfo.getId());
        findUser.setMeritPoint(findUser.getMeritPoint()+systemMeritInfo.getPoint()); //功德值*10倍活动价格
        baseDao.save(findUser, findUser.getId());

        String levelNos = findUser.getSuperior();
        if (!StrUtil.isEmpty(levelNos)) {

            Config findConfig = configService.getConfig();
            if(findConfig == null) return;

            String[] leverNoArr = levelNos.split(";");
            int i = leverNoArr.length - 1;
            for (int j = 1; i > 0; j++) {
                if (StrUtil.isNotBlank(leverNoArr[i])) {
                    UserOperator levelUser = this.operatorService.getUserOperator(leverNoArr[i]);
                    if (levelUser != null) {
                        double commissionRate = 0.0D;
                        if (j == 1)
                            commissionRate = findConfig
                                    .getFirstLevel().doubleValue();
                        else if (j == 2)
                            commissionRate = findConfig
                                    .getSecondLevel().doubleValue();
                        else if (j == 3) {
                            commissionRate = findConfig
                                    .getThirdLevel().doubleValue();
                        }

                        double commissionNum = orderInfo.getOrderSumPrice().doubleValue() * commissionRate;
                        levelUser.setCommission(Arith.getBigDecimal(levelUser.getCommission().doubleValue() + commissionNum));
                        baseDao.save(levelUser, levelUser.getId());

                        /*Commission commission = new Commission();
                        commission.setType(Integer.valueOf(1));
                        commission.setMoney(Double
                                .valueOf(commissionNum));
                        commission.setNo(String.valueOf(System
                                .currentTimeMillis()));

                        commission.setOperator(loginUser.getName());

                        commission.setUser(levelUser);

                        commission.setCreateDate(date);
                        commission.setDeleted(false);
                        commission.setLevel(Integer.valueOf(j));
                        commission.setRemark("第" + j + "级用户:编号【"
                                + loginUser.getNo() + "】购买商品奖励");
                        this.commissionService
                                .saveOrUpdate(commission);*/
                    }
                }
                i--;
            }

        }
    }

    @Override
    public boolean getOrderPayStatus(int orderId){
        OrderInfo orderInfo = getOrderInfo(orderId);
        if(orderInfo != null && IDBConstant.LOGIC_STATUS_YES.equals(orderInfo.getPayStatus())) return true;
        return false;
    }

    /********************************************************************************************************************/
    @Override
    public PageBean getOrdersIN(OrderInputView orderInputView){
        String payStatus = orderInputView.getPayStatus();
        String orderStatus = orderInputView.getOrderStatus();

        StringBuilder headSql = new StringBuilder("SELECT o.createTime, o.*, e.*, u.operatorName, u.headImg, u.operatorMobile");
        StringBuilder bodySql = new StringBuilder(" FROM order_info o, user_operator u, express_real_info e");
        StringBuilder whereSql = new StringBuilder(" WHERE o.id = u.id AND o.expressId = e.expressId");
        if(StrUtil.isNotBlank(payStatus)){
            whereSql.append(" AND payStatus = :payStatus ");
        }
        if(StrUtil.isNotBlank(orderStatus)){
            whereSql.append(" AND orderStatus = :orderStatus");
        }
        whereSql.append(" ORDER BY o.createTime DESC");

        PageBean pageBean = super.getPageBean(headSql, bodySql, whereSql, orderInputView);
        List<Map<String, Object>> list = pageBean.getList();
        for(Map<String, Object> map : list){
            String areaId = StrUtil.objToStr(map.get("areaId"));
            AreaInfo areaInfo = areaService.getById(areaId);
            if(areaInfo != null){
                map.put("areaName", AreaUtil.getThumbnailAreaName(areaInfo.getAreaNameFull()));
            }
            map.putAll(baseDao.queryBySqlFirst("SELECT itemCount FROM order_detail WHERE orderId = ?", StrUtil.objToStr(map.get("orderId"))));
        }
        return pageBean;
    }

    @Override
    public void newLogistics(OrderInfo orderInfo){
        OrderInfo orderInfoDB = getOrderInfo(orderInfo.getOrderId());
        orderInfoDB.setOrderStatus(orderInfo.getOrderStatus());
        baseDao.save(orderInfoDB, orderInfoDB.getOrderId());
    }

    @Override
    public OrderInfo getOrderInfo(int orderId){
        return baseDao.get(OrderInfo.class, orderId);
    }

    @Override
    public PageBean getOrderActivitys(OrderInputView orderInputView){

        StringBuilder headSql = new StringBuilder("SELECT o.orderSumPrice, ai.*, od.* ");
        StringBuilder bodySql = new StringBuilder(" FROM order_info o, order_detail od, activity_info ai");
        StringBuilder whereSql = new StringBuilder(" WHERE o.orderId = od.orderId AND ai.activityId = od.activityId AND o.id = :id");
        whereSql.append(" AND o.payStatus = '").append(IDBConstant.LOGIC_STATUS_YES).append("'");
        whereSql.append(" ORDER BY o.createTime DESC");

        PageBean pageBean = super.getPageBean(headSql, bodySql, whereSql, orderInputView);
        List<Map<String, Object>> list = pageBean.getList();
        for(Map<String, Object> map : list){
            map.put("activityPic", FileUtil.getImgHttp(StrUtil.objToStr(map.get("activityPic"))));
        }

        return pageBean;
    }

}
